package com.blog.controller;

import com.blog.constant.ErrorConstant;
import com.blog.constant.Types;
import com.blog.constant.WebConst;
import com.blog.dto.cond.ContentCondition;
import com.blog.exception.BusinessException;
import com.blog.model.Comment;
import com.blog.model.Content;
import com.blog.model.User;
import com.blog.service.comment.CommentService;
import com.blog.service.content.ContentService;
import com.blog.utils.IPKit;
import com.blog.utils.MethodUtil;
import com.blog.utils.ResultVoUtil;
import com.blog.utils.TaleUtils;
import com.blog.vo.ResultVo;
import com.github.pagehelper.PageInfo;
import com.vdurmont.emoji.EmojiParser;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import java.net.URLEncoder;
import java.util.List;

/**
 * 首页和关于我的页面控制器
 *
 * @author wmb
 *
 * @since 2021-2-9
 */
@Api("网站首页和关于页面")
@Controller
public class HomeController extends BaseController {

    @Autowired
    @Qualifier("contentService")
    private ContentService contentService;

    @Autowired
    @Qualifier("commentService")
    private CommentService commentService;

    @ApiOperation("文章内容页")
    @GetMapping(value = "/blog/article/{cid}")
    public String articleIndex(@NotNull(message = "文章主键不允许为空") @PathVariable("cid") Integer cid,
                                @ApiIgnore HttpServletRequest request) {
        Content content = contentService.getArticleById(cid);
        request.setAttribute("article", content);
        List<Comment> commentList = null;
        if (content != null) {
            ContentCondition contentCondition = new ContentCondition();
            contentCondition.setType(Types.ARTICLE.getType());
            // 更新文章的点击量
            this.updateArticleHit(content.getId(), content.getHits());
            commentList = commentService.getCommentsByCId(cid);
        }
        request.setAttribute("comments", commentList);
        request.setAttribute("active","blog");
        return "site/blog-details";
    }

    @ApiOperation("about首页")
    @GetMapping({"/about", "/about/index"})
    public String aboutIndex(HttpServletRequest request) {
        // 获取友情链接
        super.blogBaseData(request, null);
        request.setAttribute("active", "about");
        return "site/about";
    }

    @ApiOperation("blog首页")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageSize", value = "页数", paramType = "query", dataType = "int", defaultValue = "10", required = false)
    })
    @GetMapping(value = {"/blog/","/blog/index"})
    public String blogIndex(@RequestParam(value = "limit", defaultValue = "10", required = false) Integer pageSize,
                            @ApiIgnore HttpServletRequest request) {
        return this.blogIndex(1, pageSize, request);
    }

    @ApiOperation("blog首页-分页")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageSize", value = "页数", paramType = "query", dataType = "int", defaultValue = "10", required = false)
    })
    @GetMapping(value = "/blog/page/{p}")
    public String blogIndex(@PathVariable("p") Integer pageNum,
                            @RequestParam(value = "limit", defaultValue = "10", required = false) Integer pageSize,
                            HttpServletRequest request) {
        pageNum = pageNum < 0 || pageNum > WebConst.MAX_PAGE ? 1 : pageNum;
        ContentCondition contentCondition = new ContentCondition();
        contentCondition.setType(Types.ARTICLE.getType());
        PageInfo<Content> contentPageInfo = contentService.getArticlesByCond(contentCondition, pageNum, pageSize);
        // 文章列表
        request.setAttribute("articles", contentPageInfo);
        request.setAttribute("type", "articles");
        request.setAttribute("active", "blog");
        return "site/blog";
    }

    @ApiOperation("评论操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cid", value = "文章主键", paramType = "query", dataType = "int", required = true),
            @ApiImplicitParam(name = "coid", value = "父级评论", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "author", value = "作者", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "mail", value = "邮箱", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "url", value = "网址", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "text", value = "评论内容", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "_csrf_token", value = "_csrf_token", paramType = "query", dataType = "String", required = true)
    })
    @PostMapping(value = "/blog/comment")
    @ResponseBody
    public ResultVo comment(@NotNull(message = "文章主键不允许为空")
                                @RequestParam(name = "cid") Integer cid,
                            @RequestParam(name = "coid", required = false) Integer parentId,
                            @Size(max = 50, message = "名字不符合要求")
                                @RequestParam(name = "author", required = false) String author,
                            @Email(message = "请输入正确的邮箱地址")
                                @RequestParam(name = "mail", required = false) String mail,
                            @Pattern(regexp = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?", message = "请输入正确的URL格式")
                                @RequestParam(name = "url", required = false) String url,
                            @Size(max = 200, message = "请输入200个字符以内的评论")
                                @RequestParam(name = "text", defaultValue = "", required = true) String text,
                            @NotBlank(message = "_csrf_token不允许为空")
                                @RequestParam(name = "_csrf_token", required = true) String _csrf_token,
                            @ApiIgnore HttpServletRequest request,
                            @ApiIgnore HttpServletResponse response) {

        User user = super.user(request);

        String ref = request.getHeader("Referer");
        if (StringUtils.isBlank(ref) || StringUtils.isBlank(_csrf_token)) {
            return ResultVoUtil.error(ErrorConstant.VISIT_FAILED);
        }

        String token = cache.getSet(Types.CSRF_TOKEN.getType(), _csrf_token);
        if (StringUtils.isBlank(token)) {
            return ResultVoUtil.error(ErrorConstant.VISIT_FAILED);
        }

        String val = IPKit.getIpAddrByRequest(request) + ":" + cid;
        Integer count = cache.getSet(Types.COMMENTS_FREQUENCY.getType(), val);
        if (null != count && count > 0) {
            return ResultVoUtil.error(ErrorConstant.COMMENT_TOO_FREQUENTLY);
        }

        author = TaleUtils.cleanXSS(author);
        text = TaleUtils.cleanXSS(text);

        author = EmojiParser.parseToAliases(author);
        text = EmojiParser.parseToAliases(text);

        Comment comment = new Comment();
        comment.setAuthor(author);
        comment.setAuthorId(user.getUid());
        comment.setCid(cid);
        comment.setIp(request.getRemoteAddr());
        comment.setUrl(url);
        comment.setContent(text);
        comment.setMail(mail);
        comment.setParent(parentId);

        try {
            commentService.saveComment(comment);
            cookie("tale_remember_author", URLEncoder.encode(author, "UTF-8"), 7 * 24 * 60 * 60, response);
            cookie("tale_remember_mail", URLEncoder.encode(mail, "UTF-8"), 7 * 24 * 60 * 60, response);
            if (StringUtils.isNotBlank(url)) {
                cookie("tale_remember_url", URLEncoder.encode(url, "UTF-8"), 7 * 24 * 60 * 60, response);
            }
            // 设置对每个文章1分钟可以评论一次
            cache.set(Types.COMMENTS_FREQUENCY.getType(), val, 1, 60);

            return ResultVoUtil.success();
        } catch (Exception e) {
            throw new BusinessException(ErrorConstant.COMMENT_FAILED, MethodUtil.getLineInfo());
        }
    }


    /**
     * 更新文章的点击率
     *
     * @param cid
     * @param hits
     */
    private void updateArticleHit(Integer cid, Integer hits) {
        Integer hitCache = cache.getSet("article", "hits");
        if (hits == null) {
            hits = 0;
        }
        hitCache = hitCache == null ? 1 : hitCache + 1;
        if (hitCache >= WebConst.HIT_EXCEED) {
            // 当点击数超过10次，进行数据库值更新
            Content content = new Content();
            content.setId(cid);
            content.setHits(hits + hitCache);
            contentService.updateArticleByCid(content);
            cache.hashSet("article", "hits", 1);
        } else {
            cache.hashSet("article", "hits", hitCache);
        }
    }

    /**
     * 设置cookie
     *
     * @param name
     * @param value
     * @param maxAge
     * @param response
     */
    private void cookie(String name, String value, int maxAge, HttpServletResponse response) {
        Cookie cookie = new Cookie(name, value);
        cookie.setMaxAge(maxAge);
        cookie.setSecure(false);
        response.addCookie(cookie);
    }


}
